package com.kweative.lingua.server;

import com.kweative.cluster.Cluster;
import com.kweative.format.XmlFormat;
import com.kweative.lingua.server.protocol.Protocol;
import com.kweative.lingua.server.transport.Transport;
import com.kweative.model.data.DataProvider;
import com.kweative.model.data.MySQL;
import com.kweative.type.Node;
import com.kweative.util.KClassLoader;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author henrik
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws SQLException {
        try {
            Cluster.instance().connect();
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"Could not connect to cluster", ex);
            return;
        }
        
        if (!loadConfig()) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"Could not start due to config errors");
            return;
        }
        
        
        Server server = new Server();
        server.start();
    }
    public static boolean loadConfig() {
        XmlFormat xml = new XmlFormat();
		Node config = null;

		try {
			config = xml.parse(new File("config.xml"));
		} catch (IOException ex) {
			Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"Could not find config file", ex);
			return false;
		}
        try {
            for(Node appNode : config.getChild("apps").children()) {
                String clazz = appNode.getAttribute("class").toString();
                if (!appNode.hasAttribute("homedir")) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE,String.format("Application: %s is missing homedir attribute!",clazz));
                    continue;
                }
                File homedir = new File(appNode.getAttribute("homedir").toString());
                if (!homedir.isDirectory() || !homedir.exists()) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE,String.format("Application: Home directory doesn't exist: %s!",homedir.getAbsolutePath()));
                    continue;
                }
                
                if (appNode.hasAttribute("lib")) {
                    KClassLoader.loadJar(appNode.getAttribute("lib").toString());
                }
                Application app = (Application) KClassLoader.getInstance(clazz);
                app.setHomedir(homedir);

                if (appNode.hasAttribute("name")) {
                    app.setName(appNode.getAttribute("name").toString());
                }

                if (app == null) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE,String.format("Application: %s not found or invalid!",clazz));
                    continue;
                }
                for(Node domainNode : appNode.children()) {
                    app.addDomain(domainNode.getAttribute("name").toString());
                }
                Logger.getAnonymousLogger().log(Level.INFO,String.format("Application added: %s",app.getName()));
                Config.instance().addApplication(app);
            }
        } catch(NullPointerException ex) {}
        if (Config.instance().applications().size() == 0) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"No applications found");
            return false;
        }
        
        try {
            for(Node transportNode : config.getChild("transports").children()) {
                String clazz = (String) transportNode.getAttribute("class");
                Transport transport = (Transport) KClassLoader.getInstance(clazz);

                if (transportNode.hasAttribute("port"))
                    transport.setPort(Integer.valueOf(transportNode.getAttribute("port").toString()));

                if (transport != null) {
                    TransportPool.instance().add(transport);
                } else {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE,String.format("Transport: %s not found or invalid!",clazz));
                }
            }
        } catch(NullPointerException ex) {}
        if (TransportPool.instance().transports().size() == 0) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"No transports found");
            return false;
        }
        try {
            for(Node bindingNode : config.getChild("protocols").children()) {
                String clazz = (String) bindingNode.getAttribute("class");
                Protocol p = (Protocol) KClassLoader.getInstance(clazz);

                if (p != null) {
                    ProtocolPool.instance().add(p);
                } else {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE,String.format("Binding: %s not found or invalid!",clazz));
                }
            }
        } catch(NullPointerException ex) {}
        if (ProtocolPool.instance().protocols().size() == 0) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE,"No protocols found");
            return false;
        }

        return true;
    }

}
